//--------------------------------------------------------------------------------
/*!
\file	Channel.cpp
\author	bsmith, dkarp
\date	03/3/07
\brief	Encompasses the cursor position in the given buffer
\par	license
Copyright (c) DigiPen Institute of Technology 2006. All Rights Reserved. 
*/
//--------------------------------------------------------------------------------
#include "stdafx.h"
#include "LowLevel.h"

using namespace sndcore;
//-------------------------------------------------------------------------------
/*!
\brief Moves cursor based index
\param i
cursor index to move
\param move_pos
positions to move

\author	Ben Smith
*/
//-------------------------------------------------------------------------------
void Channel::MoveCursor( unsigned i,DWORD move_pos )
{
	if (playCursors_[i].Delayed())
		playCursors_[i].DecDelay();
	else
		playCursors_[i].pos_ += move_pos;
}
//-------------------------------------------------------------------------------
/*!
\brief Sets cursor position based on index
\param index
index of cursor
\param percentage
percentage of the sound to put cursor

\author	Ben Smith
*/
//-------------------------------------------------------------------------------
void Channel::SetCursor( const int index, float percentage )
{
	assert( percentage >= 0.0f && percentage <= 1.0f );

	if( pSound_ )
	{
		  //get end of readable buffer
		float bytes = float( pSound_->buffer_->GetFormat().wBitsPerSample >> 3 );
		float end_of_buff = ( pSound_->buffer_->GetSize()/bytes ) - 1.0f;

		  //set cursor at percentage of the end
		playCursors_[index].pos_  = DWORD( end_of_buff * percentage );

	} 
}
//-------------------------------------------------------------------------------
/*!
\brief Get length of song
\return song length in milliseconds

\author	Danny Karp
*/
//-------------------------------------------------------------------------------
int Channel::GetSongLength() const 
{ 
	if( pSound_ )
		return pSound_->GetSongLength();
	else
		return 0;
}
//-------------------------------------------------------------------------------
/*!
\brief Get bits per sample
\return bits per sample

\author Danny Karp
*/
//-------------------------------------------------------------------------------
int Channel::GetBitsPerSample() const
{
	if( pSound_ )
		return pSound_->GetBitsPerSample();
	else
		return 0;
}
//-------------------------------------------------------------------------------
/*!
\brief Get number channels
\return channels

\author	Danny Karp
*/
//-------------------------------------------------------------------------------
int Channel::GetNumChannels() const
{
	if( pSound_ )
		return pSound_->GetNumChannels();
	else
		return 0;
}
//-------------------------------------------------------------------------------
/*!
\brief Get sample rate
\return sample rate

\author	Danny Karp
*/
//-------------------------------------------------------------------------------

int Channel::GetFrequency() const
{
	if( pSound_ )
		return pSound_->GetFrequency();
	else
		return 0;
}
//-------------------------------------------------------------------------------
/*!
\brief update for streaming sounds


\author	Danny Karp
*/
//-------------------------------------------------------------------------------
void Channel::AsyncUpdate(  )
{
	//
	// See if we're streaming
	//
	if( pSound_ && pSound_->GetStream() )
	{
		
		// Can we pass data into the queue
		if( pSound_->buffer_->mlFileReadCursor >= pSound_->buffer_->mlFileTotalByteRead )
		{
			if( GetOverlappedResult( pSound_->buffer_->m_hStreamFile, &pSound_->buffer_->m_streamFileStatus,
				&pSound_->buffer_->mlFileTotalByteRead, FALSE ) == TRUE )
			{
				pSound_->buffer_->mlFileReadCursor = 0;
			}
		}


		// Do we have data ready to hand off to DSound?
		//if( pSound_->buffer_->mlFileReadCursor < pSound_->buffer_->mlFileTotalByteRead )
		if( pSound_->buffer_->mlFileReadCursor == 0 &&pSound_->buffer_->mlFileTotalByteRead >= pSound_->buffer_->mStreamBuffSize )
		{
				
			Sound *converted_sound = NULL;

			SoundBufferUser * newBuffer = new SoundBufferUser( pSound_->buffer_->options_ );

			newBuffer->WriteBuffer( pSound_->buffer_->mStreamBuffSize, pSound_->buffer_->m_streamFileBuf );

			Sound oldSound( newBuffer, false,  pSound_->GetId() );


			//resample the sound plz
			LowLevelResample( oldSound, &pSound_->mPrimaryFormat, pSound_->mSavePitchSteps, &converted_sound );
			
			StreamBuffers.push_back( converted_sound );

			pSound_->buffer_->mlFileReadCursor = pSound_->buffer_->mStreamBuffSize;

		}

		// Can we kick off a new async read?
		if( pSound_->buffer_->mlFileReadCursor >= pSound_->buffer_->mlFileTotalByteRead )
		{
			// advance the file read offset to the end of the last read
			pSound_->buffer_->m_streamFileStatus.Offset += pSound_->buffer_->mlFileTotalByteRead;
			ReadFileEx( pSound_->buffer_->m_hStreamFile, pSound_->buffer_->m_streamFileBuf, 
				                pSound_->buffer_->mStreamBuffSize, &pSound_->buffer_->m_streamFileStatus, NULL );

			DWORD err = GetLastError();
					 
			DWORD end_of_data = pSound_->buffer_->m_streamFileStatus.Offset - pSound_->buffer_->mlBeginOffset;

			bool bl_end_of_data = end_of_data >= pSound_->mStreamTotalDataSize;

			//if( end_of_data >= 1700000 )
				//err = 38;

			if( bl_end_of_data && !looping_ )
			{
				eof_reached_ = true;
			}
			  //end_of_file
			else if( bl_end_of_data  && looping_ )
			{

				pSound_->buffer_->m_streamFileStatus.Offset = pSound_->buffer_->mlBeginOffset;
				ReadFileEx( pSound_->buffer_->m_hStreamFile, pSound_->buffer_->m_streamFileBuf, 
				                pSound_->buffer_->mStreamBuffSize, &pSound_->buffer_->m_streamFileStatus, NULL );

				DWORD err = GetLastError();

			}

			
		}

	}
	
}
//-------------------------------------------------------------------------------
/*!
\brief adds the reverb dsp effect
\param power
   percentage of reverb to use of sound

\author	Ben Smith
*/
//-------------------------------------------------------------------------------
void Channel::AddReverbDSP(float power)
{
	RemoveDelayFilters();
	DWORD pos = playCursors_.back().pos_;
	playCursors_.push_back(ReadCursor(pos, 10000, power));
}
//-------------------------------------------------------------------------------
/*!
\brief Kills the cursor if it is done with the sound

\param play_index
  cursor to check
\param data_size
  size of the type

\author	Ben Smith
*/
//-------------------------------------------------------------------------------
void Channel::KillChannelTest( const int play_index, const int data_size )
{
		//if the cursor is passed its bounds then move it back to the beginning
	if( playCursors_[play_index].pos_ >= pSound_->buffer_->GetSize() / data_size ) 
	{
		playCursors_[play_index].pos_ = 0;

		  //pop off the current buffer and continue to the next one
		if( !StreamBuffers.empty() )
		{
			SAFE_DELETE( StreamBuffers.front() );
			StreamBuffers.pop_front();
		}

		if( ( looping_ == false && !pSound_->GetStream() ) ||  ( eof_reached_ && pSound_->GetStream() ) )
				playCursors_[play_index].SetPlayed(true);
	}

}

